package com.cci.kangdao.service.impl;

import com.cci.kangdao.aop.UserThreadLocal;
import com.cci.kangdao.azureAD.AzureADTool;
import com.cci.kangdao.cipFleet.service.CipFleetService;
import com.cci.kangdao.cipapi.CipServiceApi;
import com.cci.kangdao.common.RedisKeys;
import com.cci.kangdao.dao.*;
import com.cci.kangdao.dao.model.*;
import com.cci.kangdao.externalData.dto.request.LyhFileUserRequest;
import com.cci.kangdao.externalData.service.ExternalDataSynchroService;
import com.cci.kangdao.redis.RedisClientUtils;
import com.cci.kangdao.service.*;
import com.cci.kangdao.utilTool.*;
import com.cci.kangdao.wechatOrder.dao.WeChatUserRelationTDao;
import com.cci.kangdao.wechatOrder.model.WeChatUserRelationT;
import com.microsoft.aad.msal4j.IAuthenticationResult;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.message.BasicHeader;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @author 米艳春
 * @version 1.0
 * @Description: 登录、注册
 * @Company: cty
 * @date 2018-01-17
 */
@Service("loginService")
public class LoginServiceImpl implements LoginService {
    private Logger log = Logger.getLogger(this.getClass().getName());

    @Resource
    private LoginDao loginDao;
    @Resource
    private PropertiesUtils propertiesUtils;
    @Autowired
    private RedisClientUtils redisClientUtils;
    @Autowired
    private RolesTDao rolesTDao;

    @Resource
    private UserTokenTMapper userTokenTMapper;
    @Resource
    private ServiceStationDao serviceStationDao;
    @Resource
    private RolesServiceImpl rolesService;
    @Resource
    private AppVersionTDao appVersionTDao;
    @Resource
    private RolesFunctionPositionTDao rolesFunctionPositionTDao;
    @Resource
    private SystemTDao systemTDao;
    @Resource
    private UserTDao userTDao;

    @Autowired
    private MPOperationLogMapper mPOperationLogMapper;

    @Resource
    private CipFleetService cipFleetService;

    @Autowired
    private GMVisitorDao visitorDao;

    @Autowired
    private GMApplyService gmApplyService;

    @Resource
    private UserLabelMapper userLabelMapper;
    @Autowired
    private WeChatUserRelationTDao weChatUserRelationTDao;
    @Resource
    private ExternalDataSynchroService externalDataSynchroService;
    @Autowired
    private SyncEsnAndUserId syncEsnAndUserId;
    @Resource
    private MobileSmsService mobileSmsService;
    @Resource
    private DictionariesTDao dictionariesTDao;
    @Resource
    private AKeyLoginUserTokenDao aKeyLoginUserTokenDao;
    @Resource
    private CipServiceApi cipServiceApi;
    @Resource
    private SSRepairTDao ssRepairTDao;
    @Resource
    private UserChannelTMapper userChannelTMapper;
    @Resource
    private CustomerEngineRelDao customerEngineRelDao;
    @Resource
    private ServiceStationOemRelationTDao serviceStationOemRelationTDao;

    private static final List<String> HANDLE_ROLES = Arrays.asList(new String[]{"R0041"});
    private static final List<String> SS_FUNCTIONS = Arrays.asList(new String[]{"22","23","24","25","30","34","40","45","49","53"});
    private static final List<String> DR_FUNCTIONS = Arrays.asList(new String[]{"38"});

    private Pattern WWID_PATTERN = Pattern.compile("^([A-Za-z]{2})([0-9A-Za-z]{3})$");
    //活动编号
    private static final String INVITE = "invite";

    private static final String SERVICE_ENGINEER_ROLE_NO = "R0013";

    private static final String STATION_MASTER = "ROO41";


    /**
   	 * MP系统加密时间戳默认的过期时间
   	 */
   	private static long DEFAULT_EXPIRE_TIME_MS = 60000;

    /**
     * App注册用户
     *
     * @param map
     * @return
     */
    @Override
    public ModelAndView userRegister(Map map) {

        HttpServletResponse response = (HttpServletResponse) map.get("response");
        JSONObject obj = new JSONObject();
        /**
         * 验证手机号、密码是否为空
         */
        if (map.get("mobile") == null || map.get("mobile").toString().equals("")) {
            obj.put("status", -5);
            obj.put("msg", ApiErrorCode.getInstance().getErrorMsg(-5));

            //返回客户
            ParameterTool.writeResponse(response, obj.toString());
            obj = null;
            return null;
        }
        if (map.get("pwd") == null || map.get("pwd").toString().equals("")) {
            obj.put("status", -5);
            obj.put("msg", ApiErrorCode.getInstance().getErrorMsg(-5));

            //返回客户
            ParameterTool.writeResponse(response, obj.toString());
            obj = null;
            return null;
        }

        /**
         * 解密手机号+密码
         */
        String mobile = map.get("mobile").toString();
        mobile = AESTool.decryptString(mobile); //解密
        String pwd = map.get("pwd").toString();
        pwd = AESTool.decryptString(pwd); //解密
        // 加锁处理，避免发生多次提交。
        String lockKey= "aKeyLogin-" + mobile ;
        if (!redisClientUtils.lock(lockKey, 60L)) {
            //防止并发
            ParameterTool.writeErrorResponse(response, -98);
            return null;
        }
        try {
            String webClient_id = this.propertiesUtils.getPropertiesValue("webClient_id");
            String webClientSecret = this.propertiesUtils.getPropertiesValue("webClientSecret");
            String tenant = this.propertiesUtils.getPropertiesValue("tenant");
            /**
             * 1、Azure Ad获取token
             */
            /*AuthenticationResult result = AzureADTool.getAccessTokenByClient(webClient_id, webClientSecret, AUTHORITY, RESOURCE);
            if (result == null) {
                obj.put("status", -99);
                obj.put("msg", ApiErrorCode.getInstance().getErrorMsg(-99));

                //返回客户
                ParameterTool.writeResponse(response, obj.toString());
                obj = null;
                return null;
            }*/
            String token = AzureADTool.getManagementToken(tenant, webClient_id, webClientSecret);
            if (null == token) {
                ParameterTool.writeErrorResponse(response);
                return null;
            }

            /**
             * 2、Azure AD使用token去新建用户
             */
            String userJson = AzureADTool.getUser(mobile, tenant, token);
            if (StringUtils.isEmpty(userJson)) {
                // 2、Azure AD使用token去新建用户
                userJson = AzureADTool.addUser(mobile, pwd, tenant, token);
                if (StringUtils.isEmpty(userJson)) {
                    ParameterTool.writeErrorResponse(response);
                    return null;
                }
            }
            /**
             * 3、保存用户数据到数据库
             *  并给用户添加默认用户组、子用户组、角色
             */
            JSONObject jsonObj = new JSONObject(userJson);

            String username = jsonObj.getString("userPrincipalName");

            UserT bean = new UserT();
            bean.setAduserId(jsonObj.getString("id"));
            bean.setUserName(mobile);
            bean.setAzureToken("");
            bean.setPhone(mobile);
            //获取用户组
            long usergroupID = Long.valueOf(propertiesUtils.getPropertiesValue("usergroupID"));
            long usergroupSubID = Long.valueOf(propertiesUtils.getPropertiesValue("usergroupSubID"));
            bean.setUsergroupId(usergroupID);
            bean.setUsergroupId(usergroupSubID);
            /*
                 sprint58 【IP地址解析】通过IP现有注册IP解析用户的地区  jira 5998
             */
            int flag = loginDao.insertUserAddSeat(bean);
            jsonObj = null; //垃圾回收
            if (flag <= 0) {
                obj.put("status", -99);
                obj.put("msg", ApiErrorCode.getInstance().getErrorMsg(-99));

                //返回客户
                ParameterTool.writeResponse(response, obj.toString());
                return null;
            }

            // APP注册为用户添加用户组关联角色
            List<Long> roles = loginDao.userGroupHasRoleId(usergroupID);

            Long userId = bean.getId();

            for (int i = 0; i < roles.size(); i++) {
                Map<String, Object> paramsMap = new HashMap<String, Object>();
                paramsMap.put("userID", userId);
                paramsMap.put("rolesID", roles.get(i));
                loginDao.insertUserRole(paramsMap);
            }
            //添加新手活动
            log.info("添加新手活动；userId:" + bean.getId());
            cipServiceApi.addNeophyteUser(bean.getId());
            //注册时接收老友会用户
            LyhFileUserRequest userRequest = new LyhFileUserRequest();
            userRequest.setUserId(bean.getId());
            userRequest.setPhone(bean.getPhone());
            externalDataSynchroService.receiveLyhUser(userRequest);

            /**
             * 4、重新去数据获取用户数据，防止时间不正确
             */
            bean = loginDao.getUserByid(String.valueOf(bean.getId()));
            int redisCacheTime = Integer.valueOf(propertiesUtils.getPropertiesValue("redisCacheTime"));
            redisClientUtils.setObject("userT" + bean.getId(), bean, redisCacheTime);//放到redis做缓存

            String accessToken = remoteInitToken(username, pwd);
            if (StringUtils.isEmpty(accessToken)) {
                ParameterTool.writeErrorResponse(response);
                return null;
            }

            obj.put("status", 0);
            obj.put("msg", "");
            obj.put("userid", ""+bean.getId());
            obj.put("token", accessToken);
            //返回客户
            ParameterTool.writeResponse(response, obj.toString());
            obj = null;
        } catch (Exception ex) {
            log.error(ex.getMessage(), ex);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        } finally {
            //释放锁
            redisClientUtils.delkey(lockKey);
        }
        return null;
    }

    public String remoteInitToken(String username, String password) {
        //Url上包含%会报错，将其替换为%25
        password = password.replace("%", "%25");
        StringBuffer sb = new StringBuffer(this.propertiesUtils.getPropertiesValue("common.security.initToken")).append("?username=").append(username).append("&password=").append(password);
        Header accept = new BasicHeader("Accept", "application/json;odata=minimalmetadata");
        Header contentType = new BasicHeader("Content-Type", "application/json");
        String response = HttpUtils.get(sb.toString(), new ResponseHandler<String>() {
            @Override
            public String handleResponse(HttpResponse response) throws ClientProtocolException, IOException {
                if (response.getStatusLine().getStatusCode() == 200) {
                    HttpEntity httpEntity = response.getEntity();
                    return EntityUtils.toString(httpEntity);
                } else {
                    log.error("远程初始化token异常，响应：" + response);
                }
                return null;
            }
        }, accept, contentType);
        if (StringUtils.isNotEmpty(response)) {
            log.info("远程初始化token信息："+response);
            net.sf.json.JSONObject jsonObject = net.sf.json.JSONObject.fromObject(response);
            net.sf.json.JSONObject data = jsonObject.getJSONObject("data");
            if (null == data) {
                log.error("远程初始化token异常，响应：" + response);
                return null;
            } else {
                try {
                    return data.getString("token");
                } catch (Exception e) {
                    log.error("远程初始化token异常，响应：" + response);
                }
            }
        }
        return null;
    }

    /**
     * App用户登录
     *
     * @param map
     * @return
     */
    @Deprecated
    @Transactional
    public ModelAndView login(Map map) {
        try {
            HttpServletResponse response = (HttpServletResponse) map.get("response");
            JSONObject obj = new JSONObject();
            /**
             * 验证手机号、密码是否为空
             */
            if (map.get("mobile") == null || map.get("mobile").toString().equals("")) {
                obj.put("status", -5);
                obj.put("msg", ApiErrorCode.getInstance().getErrorMsg(-5));

                //返回客户
                ParameterTool.writeResponse(response, obj.toString());
                obj = null;
                return null;
            }
            if (map.get("pwd") == null || map.get("pwd").toString().equals("")) {
                obj.put("status", -5);
                obj.put("msg", ApiErrorCode.getInstance().getErrorMsg(-5));

                //返回客户
                ParameterTool.writeResponse(response, obj.toString());
                obj = null;
                return null;
            }

            /**
             * 解密手机号+密码
             */
            String mobile = map.get("mobile").toString();
            mobile = AESTool.decryptString(mobile); //解密
            String pwd = map.get("pwd").toString();
            pwd = AESTool.decryptString(pwd); //解密

            /**
             * 判断手机号码是否存在
             */
            UserT userT = loginDao.getUserByUserName(mobile);
            if (userT == null) {

                List<UserT> list = loginDao.getUserByPhone(mobile);

                if (CollectionUtils.isEmpty(list)) {
                    obj.put("status", -3);
                    obj.put("msg", ApiErrorCode.getInstance().getErrorMsg(-3));

                    //返回客户
                    ParameterTool.writeResponse(response, obj.toString());
                    obj = null;
                    return null;
                } else {
                    userT = list.get(0);
                }
            }


            String AUTHORITY = this.propertiesUtils.getPropertiesValue("authority");
            String RESOURCE = this.propertiesUtils.getPropertiesValue("resource");
            String webClient_id = this.propertiesUtils.getPropertiesValue("webClient_id");
            String webClientSecret = this.propertiesUtils.getPropertiesValue("webClientSecret");
            String tenant = this.propertiesUtils.getPropertiesValue("tenant");
            String client_id = this.propertiesUtils.getPropertiesValue("client_id");
            AUTHORITY = AUTHORITY.replace("common", tenant);
            /**
             * 1、使用Azure Ad去用户名+密码登录
             */
            IAuthenticationResult result = AzureADTool.getAccessTokenFromUserCredentials(userT.getUserName() + "@" + tenant, pwd, AUTHORITY, client_id, RESOURCE);
            if (result == null) {
                obj.put("status", -7);
                obj.put("msg", ApiErrorCode.getInstance().getErrorMsg(-7));

                //返回客户
                ParameterTool.writeResponse(response, obj.toString());
                obj = null;
                return null;
            }

            /**
             * 2、Azure Ad获取token
             */

            result = AzureADTool.getAccessTokenByClient(webClient_id, webClientSecret, AUTHORITY, RESOURCE);
            if (result == null) {
                obj.put("status", -99);
                obj.put("msg", ApiErrorCode.getInstance().getErrorMsg(-99));

                //返回客户
                ParameterTool.writeResponse(response, obj.toString());
                obj = null;
                return null;
            }
            /**
             * 3、更新用户token+时间
             */
            userT.setAzureToken(result.accessToken());
            loginDao.updateUserToken(userT);

            /**
             * 4、重新去数据获取用户数据，防止时间不正确
             */
            userT = loginDao.getUserByUserName(userT.getUserName());
            int redisCacheTime = Integer.valueOf(propertiesUtils.getPropertiesValue("redisCacheTime"));
            redisClientUtils.setObject("userT" + userT.getId(), userT, redisCacheTime);//放到redis做缓存

            obj.put("status", 0);
            obj.put("msg", "");
            obj.put("userid", ""+userT.getId());
            obj.put("token", userT.getAzureToken());
            obj.put("isPwd", userT.getIsPwd());

            //返回客户
            ParameterTool.writeResponse(response, obj.toString());
            obj = null;
        } catch (Exception ex) {
            log.error(ex.getMessage(), ex);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
        return null;
    }

    /**
     * App用户验证token接口
     *
     * @param map
     * @return
     */
    public ModelAndView verifyToken(Map map) {
        HttpServletRequest request = (HttpServletRequest) map.get("request");
        HttpServletResponse response = (HttpServletResponse) map.get("response");
        try {
            /**
             * 1、首先判断获取header中Authorization 、userid是否存在
             */
            if (request.getHeader("userid") == null || request.getHeader("userid").equals("")) {
                ParameterTool.writeErrorResponse(response, -5);
                return null;
            }
            if (request.getHeader("Authorization") == null || request.getHeader("Authorization").equals("")) {
                //返回客户
                ParameterTool.writeErrorResponse(response, -5);
                return null;
            }
            // 通过userId和token来获取数据并校验正确性
            String token = request.getHeader("Authorization");
            String userId = request.getHeader("userid");
            userId = AESTool.decryptString(userId);
            if(!NumberUtils.isDigits(userId)){
                ParameterTool.writeErrorResponse(response, -1);
                return null;
            }
            // 先获取缓存中的token
            UserTokenT userTokenT = (UserTokenT) redisClientUtils.getObject(RedisKeys.tokenKey(token));
            if (null == userTokenT) {
                // 缓存中不存在token信息，再通过用户信息获取数据库中token信息
                userTokenT = userTokenTMapper.selectByUserId(Long.valueOf(userId));
            }

            if (null == userTokenT) {
                //无法找到token相关信息
                ParameterTool.writeErrorResponse(response, -1);
                return null;
            } else {
                // 非当前用户token
                if (!userTokenT.getAccessToken().equals(token) && !redisClientUtils.exists(RedisKeys.refreshingTokenKey(token))) {
                    ParameterTool.writeErrorResponse(response, -1);
                    return null;
                }
                // 用户token在有效期
                if (LocalTimeUtil.isBefore(LocalTimeUtil.getRealCurrentTime(), userTokenT.getExpireTime())) {
                    //Map<String,Object> responseDataMap = new HashMap<>();
                    //responseDataMap.put("token",userTokenT.getAccessToken());
                    //ParameterTool.writeSuccessResponse(response, responseDataMap);
                    ParameterTool.writeSuccessResponse(response, userTokenT.getAccessToken());
                    return null;
                } else {
                    // 用户token不在有效期，通过远程刷新token
                    String accessToken = remoteRefreshToken(userId);
                    // 新token不为空，返回前端
                    if (StringUtils.isNotBlank(accessToken)) {
                        /*Map<String,Object> responseDataMap = new HashMap<>();
                        responseDataMap.put("token",accessToken);
                        ParameterTool.writeSuccessResponse(response, responseDataMap);*/
                        ParameterTool.writeSuccessResponse(response, accessToken);
                    } else {
                        // 新token为空，说明远程刷新出现问题
                        ParameterTool.writeErrorResponse(response, -1);
                    }
                }
            }
        } catch (Exception ex) {
            log.error(ex.getMessage(), ex);
            ParameterTool.writeErrorResponse(response);
        }
        return null;
    }

    public String remoteRefreshToken(String userId) {
        StringBuffer sb = new StringBuffer(this.propertiesUtils.getPropertiesValue("common.security.refreshToken")).append("?userId=").append(userId);
        Header accept = new BasicHeader("Accept", "application/json;odata=minimalmetadata");
        Header contentType = new BasicHeader("Content-Type", "application/json");
        String response = HttpUtils.get(sb.toString(), new ResponseHandler<String>() {
            @Override
            public String handleResponse(HttpResponse response) throws ClientProtocolException, IOException {
                if (response.getStatusLine().getStatusCode() == 200) {
                    HttpEntity httpEntity = response.getEntity();
                    return EntityUtils.toString(httpEntity);
                } else {
                    log.error("远程刷新token异常，响应：" + response);
                }
                return null;
            }
        }, accept, contentType);
        if (StringUtils.isNotEmpty(response)) {
            log.info("远程刷新token信息：" + response);
            net.sf.json.JSONObject jsonObject = net.sf.json.JSONObject.fromObject(response);
            net.sf.json.JSONObject data = jsonObject.getJSONObject("data");
            if (null == data) {
                log.error("远程刷新token异常，响应：" + response);
                return null;
            } else {
                try {
                    return data.getString("token");
                } catch (Exception e) {
                    log.error("远程刷新token异常，响应：" + response);
                }
            }
        }
        return null;
    }

    /**
     * App用户修改密码接口
     *
     * @param map
     * @return
     */
    public ModelAndView updateUserpwd(Map map) {
    	 HttpServletRequest request = (HttpServletRequest) map.get("request");
         HttpServletResponse response = (HttpServletResponse) map.get("response");
        try {
            /**
             * 1、检查密码是否为空
             */
            JSONObject obj = new JSONObject();
            if (map.get("pwd") == null || map.get("pwd").toString().equals("")) {
                obj.put("status", -5);
                obj.put("msg", ApiErrorCode.getInstance().getErrorMsg(-5));

                //返回客户
                ParameterTool.writeResponse(response, obj.toString());
                obj = null;
                return null;
            }

            /**
             * 解密密码
             */
            String pwd = map.get("pwd").toString();
            pwd = AESTool.decryptString(pwd); //解密
            /**
             * 2、redis中获取userT信息
             */
            String userid = request.getHeader("userid");

            if(StringUtils.isBlank(userid)) {
            	userid  = map.get("userId").toString();
            }

            userid = AESTool.decryptString(userid);//AES解密

            UserT userT = (UserT) redisClientUtils.getObject("userT" + userid);

            if(Objects.isNull(userT)) {
            	userT = loginDao.getUserByid(userid);
            }

            if(WWID_PATTERN.matcher(userT.getUserName()).matches()){
                ParameterTool.writeResponse(response,1,"您为康明斯内部用户，暂不支持修改密码");
                return null;
            }
            if(pwd.contains(userT.getUserName())){
                ParameterTool.writeResponse(response,2,"您好，您输入的密码不能包含用户名信息，请修改");
                return null;
            }

            String AUTHORITY = this.propertiesUtils.getPropertiesValue("authority");
            String RESOURCE = this.propertiesUtils.getPropertiesValue("resource");
            String webClient_id = this.propertiesUtils.getPropertiesValue("webClient_id");
            String webClientSecret = this.propertiesUtils.getPropertiesValue("webClientSecret");
            String tenant = this.propertiesUtils.getPropertiesValue("tenant");

            AUTHORITY = AUTHORITY.replace("common", tenant);
            IAuthenticationResult result = AzureADTool.getAccessTokenByClient(webClient_id, webClientSecret,AUTHORITY,RESOURCE);
            if(result == null){
                obj.put("status", -99);
                obj.put("msg", ApiErrorCode.getInstance().getErrorMsg(-99));

                //返回客户
                ParameterTool.writeResponse(response, obj.toString());
                obj = null;
                return null;
            }
            /**
             * 3.2Azure AD修改密码
             */
            boolean flag = AzureADTool.chagePasswordAzureUser(userT.getAduserId(), pwd, result.accessToken(), tenant);

            if(!flag){
                obj.put("status", -99);
                obj.put("msg", ApiErrorCode.getInstance().getErrorMsg(-99));

                //返回客户
                ParameterTool.writeResponse(response, obj.toString());
                obj = null;
                return null;
            }

            /*String webClient_id = this.propertiesUtils.getPropertiesValue("webClient_id");
            String webClientSecret = this.propertiesUtils.getPropertiesValue("webClientSecret");
            String tenant = this.propertiesUtils.getPropertiesValue("tenant");
            String token = AzureADTool.getManagementToken(tenant, webClient_id, webClientSecret);
            if (StringUtils.isEmpty(token)) {
                ParameterTool.writeErrorResponse(response);
                return null;
            }
            Boolean flag = AzureADTool.modifyUserPassword(tenant, userT.getUserName(), token, pwd);

            if (!flag) {
                ParameterTool.writeErrorResponse(response);
                return null;
            }*/
            /**
             * 3.3修改密码成功后判断是否是首次修改密码，如果为首次修改密码则更改数据库
             */
            if (userT.getIsPwd() == 0) {
                loginDao.updateUserIsPwd(userT);
            }

            obj.put("status", 0);
            obj.put("msg", "");
            //返回客户
            ParameterTool.writeResponse(response, obj.toString());
            obj = null;
        } catch (Exception ex) {
            log.error(ex.getMessage(), ex);
            ParameterTool.writeErrorResponse(response);
        }
        return null;
    }


    @Override
    public void mpUpdateUserPassword(Map<String, Object> map) {
    	log.info("来自Mp系统的参数:" + map);

		try {
			Object secretKeyObj = map.get("secretKey");

	    	if(Objects.isNull(secretKeyObj)) {
	    		ParameterTool.writeResponse((HttpServletResponse)map.get("response"), 500, "参数secretKeyObj不能为空");
	            return;
	    	}
			String timeStampStr = AESTool.decryptString(secretKeyObj.toString());
			// 校验时间戳是否过期
			// MP系统传过来的时间戳
			long mpTimeStamp = Long.parseLong(timeStampStr);
			// 当前系统的时间戳
			SimpleDateFormat sdf = new SimpleDateFormat(LocalTimeUtil.DTF_FORMATTER);
			sdf.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
			String realCurrentTime = LocalTimeUtil.getRealCurrentTime();
			long currentTimeStamp = sdf.parse(realCurrentTime).getTime();

			// 默认时间戳的过期时间为60秒
			if((mpTimeStamp + DEFAULT_EXPIRE_TIME_MS) < currentTimeStamp || mpTimeStamp > (currentTimeStamp + 5000)) {
				log.error(String.format("北京时间:%s 北京时间戳:%s ",realCurrentTime, currentTimeStamp));
				ParameterTool.writeResponse((HttpServletResponse)map.get("response"), 500, "参数secretKey过期");
				return;
			}
		} catch (Exception e) {
			ParameterTool.writeResponse((HttpServletResponse)map.get("response"), 500, "参数secretKey错误");
            return;
		}

		Object username = map.get("username");
		if(Objects.isNull(username)) {
			ParameterTool.writeResponse((HttpServletResponse)map.get("response"), 500, "参数username不能为空");
            return;
		}

		UserT user = loginDao.getUserByUserName(username.toString());

		if(Objects.isNull(user)) {
			ParameterTool.writeResponse((HttpServletResponse)map.get("response"), -100, "用户不存在");
            return;
		}

    	Object userIdObj = map.get("userId");
    	if(!Objects.isNull(userIdObj) && StringUtils.isNotBlank(userIdObj.toString())) {
    		map.put("userId", AESTool.encryptString(user.getId()+""));
    		map.put("pwd", map.get("password"));
    		updateUserpwd(map);
    	}else {
    		map.put("userId", AESTool.encryptString(user.getId()+""));
    		findPassword(map);
    	}

    	map.put("createTime", LocalTimeUtil.getRealCurrentTime());
    	// 保存操作日志
    	mPOperationLogMapper.insert(map);

    }

    @SuppressWarnings("unchecked")
	@Override
    public ModelAndView findPassword(Map map) {
        try {
            HttpServletResponse response = (HttpServletResponse) map.get("response");

            String password = map.get("password").toString();
            if (StringUtils.isEmpty(password)) {
                ParameterTool.writeErrorResponse(response, -5);
                return null;
            }
           //解密
            password = AESTool.decryptString(password);

            UserT userT = null;
            /**
             * 2021-05-18 Guidanz修改密码与e路App修改密码做了整合
             * source==0说明修改源来自GuidanzApp
             */
            if(MapUtils.getIntValue(map, "source", -1) == 0) {
            	// 当参数校验正常时会返回User对象，异常时会返回null并且会响应错误信息
            	userT = checkParamFromGuidanz(map);
            	if(userT == null) {
            		return null;
            	}
            }else {
                String userIdStr = map.get("userId").toString();
                if (StringUtils.isEmpty(password) || StringUtils.isEmpty(userIdStr)) {
                    ParameterTool.writeErrorResponse(response, -5);
                    return null;
                }
                userIdStr = AESTool.decryptString(userIdStr);
                Long userId = Long.valueOf(userIdStr);
                userT = loginDao.getUserByUserId(userId);
                if(null == userT){
                    ParameterTool.writeErrorResponse(response,-3);
                    return null;
                }
            }


            if(WWID_PATTERN.matcher(userT.getUserName()).matches() && userT.getIsType() == 2){
                ParameterTool.writeResponse(response,1,"您为康明斯内部用户，暂不支持找回密码");
                return null;
            }
            if(password.contains(userT.getUserName())){
                ParameterTool.writeResponse(response,2,"您好，您输入的密码不能包含用户名信息，请修改");
                return null;
            }

            //=============================================更新AD池里的用户密码============================================
            //连接AD
            String AUTHORITY = this.propertiesUtils.getPropertiesValue("authority");
            String RESOURCE = this.propertiesUtils.getPropertiesValue("resource");
            String webClient_id = this.propertiesUtils.getPropertiesValue("webClient_id");
            String webClientSecret = this.propertiesUtils.getPropertiesValue("webClientSecret");
            String tenant = this.propertiesUtils.getPropertiesValue("tenant");
            //获取token
            AUTHORITY = AUTHORITY.replace("common", tenant);
            IAuthenticationResult result = AzureADTool.getAccessTokenByClient(webClient_id, webClientSecret,AUTHORITY,RESOURCE);
            if(result == null){
                ParameterTool.writeErrorResponse(response);
                return null;
            }
            //修改密码
            boolean flag = AzureADTool.chagePasswordAzureUser(userT.getAduserId(), password, result.accessToken(), tenant);
            if(!flag){
                ParameterTool.writeErrorResponse(response);
                return null;
            }

            /**
             * 3.3修改密码成功后判断是否是首次修改密码，如果为首次修改密码则更改数据库
             */
            if (userT.getIsPwd() == 0) {
                loginDao.updateUserIsPwd(userT);
            }

            //===============================================初始化token==================================================
            //远程刷新token
            String username = userT.getUserName()+"@"+tenant;
            String token = remoteInitToken(username,password);

            if(StringUtils.isEmpty(token)){
                ParameterTool.writeErrorResponse(response);
                return null;
            }
            Map<String,Object> responseDataMap = new HashMap<>();
            responseDataMap.put("userId",String.valueOf(userT.getId()));
            responseDataMap.put("token",token);
            responseDataMap.put("isPwd",userT.getIsPwd());
            ParameterTool.writeSuccessResponse(response,responseDataMap);
        } catch (Exception ex) {
            log.error(ex.getMessage(), ex);
        }
        return null;
    }


    /**
     * 校验Guidanz修改密码时，所传参数是否正确
     * @return
     */
    private UserT checkParamFromGuidanz(Map<String, Object> map) {
    	 HttpServletResponse response = (HttpServletResponse) map.get("response");
    	// updateType 修改方式  0：手机短信修改  1：邮箱修改  目前app没有提供邮箱修改
    	int updateType = MapUtils.getIntValue(map, "updateType", -1);
    	String mobile = MapUtils.getString(map, "mobile");

    	if(updateType == 0 && StringUtils.isNotEmpty(mobile)) {
    		// 根据手机号查询出对应的帐号 注：正常情况下最多查询出一个，但不排除数据错误的可能
    		List<UserT> users = userTDao.getUserByNameOrPhone(mobile);
    		if(CollectionUtils.isEmpty(users)) {
    			ParameterTool.writeResponse(response, 110, "手机号可能未注册");
        		return null;
    		}else if(users.size() >= 2) {
    			ParameterTool.writeResponse(response, 120, "手机号存在异常");
        		return null;
    		}

    		// 校验验证码是否正确
    		if(!isValidSMSVerityCode(MapUtils.getString(map, "verifyCode"), mobile)) {
    			ParameterTool.writeErrorResponse(response, -6);
        		return null;
    		}

    		return users.get(0);
    	}else {
    		ParameterTool.writeResponse(response, 100, "参数错误");
    		return null;
    	}
    }


    /**
     * 校验短信验证码是否有效
     */
    private boolean isValidSMSVerityCode(String code, String mobile) {
    	if(StringUtils.isNotEmpty(code)) {
    		// 从Redis里获取缓存的手机验证码
    		String redisCode = redisClientUtils.get("sms" + mobile);
    		log.info(String.format("手机号：%s的验证码为：%s", mobile, redisCode));
    		return code.equals(redisCode);
    	}
    	return false;
    }



    /**
     * App用户获取首页功能
     *
     * @param map
     * @return
     */
    @Override
    public ModelAndView index(Map map) {
        try {
            HttpServletRequest request = (HttpServletRequest) map.get("request");
            HttpServletResponse response = (HttpServletResponse) map.get("response");
            /**
             * 1、redis中获取userT信息
             */
            JSONObject obj = new JSONObject();
            String userid = request.getHeader("userid");
            userid = AESTool.decryptString(userid);//AES解密
            UserT userT = (UserT) redisClientUtils.getObject("userT" + userid);
            Integer s = 0;
            if (redisClientUtils.exists("Common-VIDEOSUBMISSIONS")){
                s = Integer.parseInt(redisClientUtils.get("Common-VIDEOSUBMISSIONS"));
            }

             //活动是否开启
//            List<ActivityT> activityList = inviteDao.getActivityList();
//            List<ActivityResponse> activityResponseList = new ArrayList<>();
//            for(ActivityT activity : activityList){
//                if(null != activity && activity.getIsOpen().equals(1)
//                        && StringUtils.isNotEmpty(activity.getEndTime())
//                        && LocalTimeUtil.isBefore(LocalTimeUtil.getRealCurrentTime(),activity.getEndTime())
//                ){
//                    //活动白名单
//                    boolean isAdd = false;
//                    int count = inviteDao.activityWhite(activity.getActivityCode(),null);
//                    if(count > 0){
//                        int isCount = inviteDao.activityWhite(activity.getActivityCode(),userT.getPhone());
//                        if(isCount > 0){
//                            isAdd = true;
//                        }
//                    } else {
//                        isAdd = true;
//                    }
//                    if(isAdd){
//                        ActivityResponse  activityResponse = BeanUtils.convert(activity,ActivityResponse.class);
//                        activityResponseList.add(activityResponse);
//                    }
//                }
//            }

            if(null == userT){
                if(NumberUtils.isDigits(userid)){
                    userT = loginDao.getUserByUserId(Long.valueOf(userid));
                    if(null != userT){
                        int redisCacheTime = Integer.valueOf(propertiesUtils.getPropertiesValue("redisCacheTime"));
                        redisClientUtils.setObject("userT" + userT.getId(), userT, redisCacheTime);
                    }
                }
            }
            //初始化登录人是否具有服务流程权限   默认值为0   否
            int sSFunStatus = 0;
            //初始化登录人是否具有诊断维修权限   默认值为0   否
            int dRFunStatus = 0;
            if(null != userT){
                String authorizeCompanyNo = "";
                if(userT.getServiceStationID() != 0){
                    Map<String,Object> serviceStationT = serviceStationDao.getServiceStationById(userT.getServiceStationID());
                    if(null != serviceStationT && serviceStationT.size() > 0){
                        authorizeCompanyNo = ssRepairTDao.getCompanyNoByServiceStationId(userT.getServiceStationID());
                        sSFunStatus = Integer.parseInt(serviceStationT.get("SSFunStatus").toString());
                        dRFunStatus = Integer.parseInt(serviceStationT.get("DRFunStatus").toString());
                    }
                }

                /**
                 * 2、获取用户的功能
                 */
                obj.put("status", 0);
                obj.put("msg", "");
                obj.put("activityButtonStatus", s);
                obj.put("authorizeCompanyNo", authorizeCompanyNo);
                //obj.put("activityList", com.alibaba.fastjson.JSONArray.parseArray(JSON.toJSONString(activityResponseList)));
                JSONArray array = new JSONArray();  //返给前端的功能项json集合数据
                List<FunctionT> functionList = loginDao.getAllFunctionByUserid(userT.getId());
                long systemId = Long.valueOf(propertiesUtils.getPropertiesValue("systemId"));
                if (CollectionUtils.isNotEmpty(functionList)) {
                    int weightMax = 0;
                    Set<Integer> collect = functionList.stream().map(FunctionT::getWeight).filter(Objects::nonNull).collect(Collectors.toSet());
                    if (CollectionUtils.isNotEmpty(collect)){
                        weightMax = collect.stream().max(Integer::compare).get();
                    }
                    JSONArray fuArray = new JSONArray();  //保存所有父级功能项json集合数据
                    JSONArray ziArray = new JSONArray();  //保存所有子级功能项json集合数据
                    for (FunctionT functionT : functionList) {  //遍历所有功能项目，不分父子项
                        if(userT.getServiceStationID() != 0){
                            if(sSFunStatus == 0){  //这个服务站没有服务流程的权限
                                if("23".equals(functionT.getFunUrl()) || "24".equals(functionT.getFunUrl())){
                                    continue;
                                }
                            }
                            if(dRFunStatus == 0){  //这个服务站没有诊断维修的权限
                                if("38".equals(functionT.getFunUrl())){
                                    continue;
                                }
                            }
                            //如果是服务站用户   如果该服务站没有被大运授权   则不展示预约维保功能项
                            int isDYAuthorizationCount = serviceStationOemRelationTDao.getServiceStationOemRelationCountByStationId(userT.getServiceStationID());
                            if(isDYAuthorizationCount <= 0 && "89".equals(functionT.getFunUrl())){
                                continue;
                            }
                        }
                        if (functionT.getSystemID() == systemId && functionT.getFatherID() == 0) {  //保存所有父级功能项
                            JSONObject json = new JSONObject();
                            json.put("id", functionT.getId());
                            json.put("fUrl", functionT.getFunUrl());
                            json.put("fName", functionT.getFunctionName());
                            json.put("weight", functionT.getWeight());
                            json.put("isHighFunction", functionT.getIsHighFunction());
                            fuArray.put(json);
                        }
                        if (functionT.getSystemID() == systemId && functionT.getFatherID() != 0) {  //保存所有子级功能项
                            JSONObject json = new JSONObject();
                            //json.put("id", functionT.getId());
                            json.put("fatherID", functionT.getFatherID());
                            json.put("fUrl", functionT.getFunUrl());
                            json.put("fName", functionT.getFunctionName());
                            json.put("isHighFunction", functionT.getIsHighFunction());
                            ziArray.put(json);
                        }
                    }
                    fuArray = sortFunction(userT.getId(),fuArray);
                    for (int i = 0; i < fuArray.length(); i++) {   //遍历父级功能项
                        JSONObject json = new JSONObject();    //返给前端得json数据
                        JSONObject fuJob = fuArray.getJSONObject(i);   //获取当前父级功能项
                        json.put("fUrl", fuJob.get("fUrl"));   //功能url
                        json.put("fName", fuJob.get("fName"));  //
                        if (StringUtils.isNotEmpty(fuJob.optString("weight"))){    // 新增权重 - spencer需求
                            json.put("weight", fuJob.get("weight") );
                        } else {
                            weightMax += 10;
                            json.put("weight", weightMax);
                        }
                        json.put("isHighFunction", fuJob.get("isHighFunction"));
                        //json.put("type",null==fuJob.get("type")?"1":fuJob.get("type"));
                        JSONArray subFunction = new JSONArray();  //子功能项
                        for (int j = 0; j < ziArray.length(); j++) {   //遍历子级功能项
                            JSONObject ziJob = ziArray.getJSONObject(j);   //获取当前子功能项
                            //判断当前得子功能项得父id是否和父级功能项相等，若相等就加入到subFunction中
                            if (Long.parseLong(fuJob.get("id").toString()) == Long.parseLong(ziJob.get("fatherID").toString())) {
                                JSONObject ziJson = new JSONObject();
                                ziJson.put("fUrl", ziJob.get("fUrl"));
                                ziJson.put("fName", ziJob.get("fName"));
                                ziJson.put("isHighFunction", ziJob.get("isHighFunction"));
                                subFunction.put(ziJson);
                            }
                        }
                        json.put("subFunction", subFunction);
                        array.put(json);
                    }
                }
                obj.put("funtions", array);
            } else {
                obj.put("status", 0);
                obj.put("msg", "");
                obj.put("funtions", new JSONArray());
            }
            //返回客户
            ParameterTool.writeResponse(response, obj.toString());
            obj = null;
        } catch (Exception ex) {
            log.error(ex.getMessage(), ex);
        }
        return null;
    }


    /**
     * npbu项目接口     npbu根据角色获取e路康明斯app上npbu首页菜单（轮播图，功能项，文章分类）
     *
     * @param map
     * @return
     */
    @Override
    public ModelAndView npbuIndexMenu(Map map) {
        try {
            HttpServletResponse response = (HttpServletResponse) map.get("response");
            JSONObject obj = new JSONObject();
            UserT userT = UserThreadLocal.get();
            if(null != userT){
                List<Map<String,Object>> npbuFunListScope = dictionariesTDao.getDictionariesListByDTableName("npbuFunListScope");
                String npbuFunListScope1 = "";
                String npbuFunListScope2 = "";
                if(CollectionUtils.isNotEmpty(npbuFunListScope)){
                    npbuFunListScope1 = MapUtils.getString(npbuFunListScope.get(0),"DValue","");
                    npbuFunListScope2 = MapUtils.getString(npbuFunListScope.get(1),"DValue","");
                }
                List<String> npbuFunListScope2List = new ArrayList<>();
                if(StringUtils.isNotEmpty(npbuFunListScope2)){
                    npbuFunListScope2List = Arrays.asList(npbuFunListScope2.split(","));
                }

                /**
                 * 2、获取用户的功能
                 */
                obj.put("status", 0);
                obj.put("msg", "success");
                JSONArray array = new JSONArray();  //返给前端的功能项json集合数据
                List<FunctionT> functionList = loginDao.getAllFunctionByUserid(userT.getId());
                long systemId = Long.valueOf(propertiesUtils.getPropertiesValue("systemId"));
                if (CollectionUtils.isNotEmpty(functionList)) {
                    JSONArray fuArray = new JSONArray();  //保存所有父级功能项json集合数据
                    JSONArray ziArray = new JSONArray();  //保存所有子级功能项json集合数据
                    for (FunctionT functionT : functionList) {  //遍历所有功能项目，不分父子项
                        if (functionT.getSystemID() == systemId && functionT.getFatherID() == 0) {  //保存所有父级功能项
                            JSONObject json = new JSONObject();
                            json.put("id", functionT.getId());
                            json.put("fUrl", functionT.getFunUrl());
                            json.put("fName", functionT.getFunctionName());
                            fuArray.put(json);
                        }
                        if (functionT.getSystemID() == systemId && functionT.getFatherID() != 0) {  //保存所有子级功能项
                            JSONObject json = new JSONObject();
                            json.put("fatherID", functionT.getFatherID());
                            json.put("fUrl", functionT.getFunUrl());
                            json.put("fName", functionT.getFunctionName());
                            ziArray.put(json);
                        }
                    }
                    fuArray = sortFunction(userT.getId(),fuArray);
                    for (int i = 0; i < fuArray.length(); i++) {   //遍历父级功能项
                        JSONObject json = new JSONObject();    //返给前端得json数据
                        JSONObject fuJob = fuArray.getJSONObject(i);   //获取当前父级功能项
                        String fUrl = fuJob.get("fUrl").toString();
                        if("316".equals(fUrl)){   //316是新能源专区的funurl
                            json.put("fUrl", fUrl);   //功能url
                            json.put("fName", fuJob.get("fName"));  //
                            JSONArray subFunction = new JSONArray();  //子功能项
                            for (int j = 0; j < ziArray.length(); j++) {   //遍历子级功能项
                                JSONObject ziJob = ziArray.getJSONObject(j);   //获取当前子功能项
                                //判断当前得子功能项得父id是否和父级功能项相等，若相等就加入到subFunction中
                                if (Long.parseLong(fuJob.get("id").toString()) == Long.parseLong(ziJob.get("fatherID").toString())) {
                                    JSONObject ziJson = new JSONObject();
                                    String zifName = ziJob.get("fName").toString();
                                    if(npbuFunListScope1.contains(zifName)){
                                        ziJson.put("fMenuType", 1);    //1代表服务手册,服务工具,技术培训,零件查询,体验馆,智能诊断,数字化
                                    }
                                    if(npbuFunListScope2.contains(zifName)){
                                        ziJson.put("fMenuType", 2);    //2代表服务公告-2,产品资讯-3,经验分享-4
                                        if(CollectionUtils.isNotEmpty(npbuFunListScope2List)){
                                            for(String npbuFunListScope2Str : npbuFunListScope2List){
                                                if(npbuFunListScope2Str.contains(zifName)){
                                                    int fMenuTypeDInt = Integer.parseInt(npbuFunListScope2Str.substring(npbuFunListScope2Str.indexOf("-")+1));
                                                    ziJson.put("fMenuTypeDInt", fMenuTypeDInt);
                                                    break;
                                                }
                                            }
                                        }
                                    }
                                    ziJson.put("fUrl", ziJob.get("fUrl"));
                                    ziJson.put("fName", ziJob.get("fName"));
                                    subFunction.put(ziJson);
                                }
                            }
                            json.put("subFunction", subFunction);
                            array.put(json);
                        }
                    }
                }
                obj.put("funtions", array);
            } else {
                obj.put("status", 0);
                obj.put("msg", "success");
                obj.put("funtions", new JSONArray());
            }
            //返回客户
            ParameterTool.writeResponse(response, obj.toString());
            obj = null;
        } catch (Exception ex) {
            log.error(ex.getMessage(), ex);
        }
        return null;
    }


    /**
     * npbu获取用户的所有动作     npbu根据角色获取e路康明斯app上npbu首页菜单（轮播图，功能项，文章分类）
     *
     * @param map
     * @return
     */
    @Override
    public ModelAndView getNpbuActionByUserid(Map map) {
        try {
            HttpServletResponse response = (HttpServletResponse) map.get("response");
            JSONObject obj = new JSONObject();
            UserT userT = UserThreadLocal.get();
            if(null != userT){
                List<ActionT> actionList = loginDao.getAllActionByUserid(userT.getId());
                obj.put("status", 0);
                obj.put("msg", "success");
                JSONArray array = new JSONArray();  //返给前端的功能项json集合数据
                if (CollectionUtils.isNotEmpty(actionList)) {
                    for (ActionT actionT : actionList) {  //遍历所有功能项目，不分父子项
                        JSONObject json = new JSONObject();    //返给前端得json数据
                        json.put("actionName", actionT.getActionName());
                        json.put("actionUrl", actionT.getActionUrl());  //
                        array.put(json);
                    }
                }
                obj.put("actions", array);
            } else {
                obj.put("status", 0);
                obj.put("msg", "success");
                obj.put("actions", new JSONArray());
            }
            //返回客户
            ParameterTool.writeResponse(response, obj.toString());
            obj = null;
        } catch (Exception ex) {
            log.error(ex.getMessage(), ex);
        }
        return null;
    }

    private JSONArray sortFunction(Long userId,JSONArray src){
        JSONArray sorted = new JSONArray();
        List<Map<String,Object>> roleMapList = loginDao.getUserRoles(userId);
        if(CollectionUtils.isNotEmpty(roleMapList)){
            //拼装原功能项对象，若未排序则追加至最后。
            Map<Long,JSONObject> srcMap = new LinkedHashMap<>(src.length());
            for(int i=0;i<src.length();i++){
                try {
                    JSONObject jsonObject = src.getJSONObject(i);
                    Long funId = (Long) jsonObject.get("id");
                    srcMap.put(funId,jsonObject);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            // TODO: 2019/6/13 随机选取第一个角色为排序参照，可能导致多角色用户功能排序非预期的问题
            Map<String,Object> roleMap = roleMapList.get(0);
            List<Map<String,Object>> sortedFunctionPosition = rolesFunctionPositionTDao.getRolesFunctionPositionByRoleId((Long) roleMap.get("ID"));
            if(CollectionUtils.isNotEmpty(sortedFunctionPosition)){
                for(Map<String,Object> sortMap : sortedFunctionPosition){
                    for(int i=0;i<src.length();i++){
                        try {
                            JSONObject jsonObject = src.getJSONObject(i);
                            Long funId = (Long) jsonObject.get("id");
                            if(sortMap.get("FunId").equals(funId)){
                                //jsonObject.put("type",sortMap.get("FunType"));
                                sorted.put(jsonObject);
                                srcMap.remove(funId);
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
                if(MapUtils.isNotEmpty(srcMap)){
                    for(JSONObject jsonObject :srcMap.values()){
                        sorted.put(jsonObject);
                    }
                }
            }else {
                sorted = src;
            }
        }else{
            sorted = src;
        }
        return sorted;
    }

    /**
     * web请求删除redis中的key
     *
     * @param map
     * @return
     */
    @Override
    public ModelAndView delRedisKey(Map map) {
        try {
            HttpServletResponse response = (HttpServletResponse) map.get("response");
            /**
             * 1、获取key的值
             */
            JSONObject obj = new JSONObject();
            if (map.get("key") == null || map.get("key").toString().equals("")) {
                obj.put("status", -1);
                obj.put("msg", "请输入key");
                //返回客户
                ParameterTool.writeResponse(response, obj.toString());
                obj = null;
            }
            String redisKey = map.get("key").toString();
            /**
             * 2、清楚redis中缓存中的key
             */
            if (redisKey.equals("all")) {
                //删除所有的key
                redisClientUtils.delAllkey();

            } else {
                //删除指定key
                redisClientUtils.delkey(redisKey);
            }
            obj.put("status", 0);
            obj.put("msg", "");
            //返回客户
            ParameterTool.writeResponse(response, obj.toString());
            obj = null;
        } catch (Exception ex) {
            log.error(ex.getMessage(), ex);
        }
        return null;
    }

    @Override
    public String getApiDomain(Map<String,Object> map) {
        JSONObject obj = new JSONObject();
        HttpServletResponse response = (HttpServletResponse) map.get("response");
        try {
            // 默认设置为线上地址
            String apiDomain = redisClientUtils.get("API_DOMAIN");
            if (StringUtils.isBlank(apiDomain)) {
                apiDomain = loginDao.getApiDomain();
                int redisCacheTime = Integer.valueOf(propertiesUtils.getPropertiesValue("redisCacheTime"));
                redisClientUtils.set("API_DOMAIN", apiDomain, redisCacheTime);
            }
            // 前端版本号
            String version = MapUtils.getString(map,"version");
            // 版本号不为空，查询对应地址
            if(StringUtils.isNotEmpty(version)){
                // 获取最大IOS发布版本
                String maxVersion = appVersionTDao.selectMaxIOSVersion();
                // 如果最大版本号小于当前版本，取测试环境地址
                if(maxVersion.compareTo(version) < 0){
                    String url = systemTDao.getTestSystemUrl();
                    if(StringUtils.isNotEmpty(url)){
                        apiDomain = url;
                    }
                }
            }
            obj.put("status", 0);
            obj.put("msg", "");
            obj.put("apiHost", apiDomain);
        } catch (JSONException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        ParameterTool.writeResponse(response, obj.toString());
        return "";
    }

    @Override
    public ModelAndView getLoginUrl(Map map) {
        HttpServletResponse response = (HttpServletResponse) map.get("response");
        String account = (String) map.get("account");
        String type = (String) map.get("type");
        // 用户选择手机号/帐号登录时 type=1
        // 用户选择康明斯员工登录登录时 type=2
        //参数校验，account+type均不为空，且type=1或2
        if(StringUtils.isEmpty(account) || StringUtils.isEmpty(account)){
            ParameterTool.writeErrorResponse(response,-5);
            return null;
        }else{
            if(!type.equals("1") && !type.equals("2")){
                ParameterTool.writeErrorResponse(response,-5);
                return null;
            }
        }
        //查询手机号对应的用户数据
        // TODO: 2019/4/29 刷新数据之后，并不存在通过phone获取username的逻辑
        if(type.equals("1")){
            UserT userT = loginDao.getUserByUserName(account);
            if(null == userT){
                List<UserT> userTList = loginDao.getUserByPhone(account);
                if(CollectionUtils.isEmpty(userTList)){
                    ParameterTool.writeErrorResponse(response,-3);
                    return null;
                }else{
                    userT = userTList.get(0);
                }
            }
            if(null != userT){
                account = userT.getUserName();
                Integer userType = userT.getType();
                if(2 == userType){
                    ParameterTool.writeResponse(response,2,"");
                    return null;
                }
            }
        }

        String tenant = propertiesUtils.getPropertiesValue("tenant");
        String authorizationClientId = propertiesUtils.getPropertiesValue("client_id");
        StringBuffer sb = new StringBuffer("https://login.partner.microsoftonline.cn/")
                .append(tenant)
                .append("/oauth2/v2.0/authorize?response_type=code&scope=openid profile offline_access https://microsoftgraph.chinacloudapi.cn/User.Read&client_id=")
                .append(authorizationClientId)
                .append("&state=chinalocal&login_hint=")
                .append(account)
                .append("@");
        if(type.equals("1")){
            sb.append(tenant);
        }else {
            String innerTenant = propertiesUtils.getPropertiesValue("innerTenant");
            sb.append(innerTenant);
        }

        Map<String,Object> urlMap = new HashMap<>();
        urlMap.put("url", sb.toString());
        ParameterTool.writeSuccessResponse(response, urlMap);
        return null;
    }

    @Override
    @Transactional
    public void initInfo(Map<String, Object> map) {
        HttpServletResponse response = (HttpServletResponse) map.get("response");
        try {
            // 获取请求参数
            String adUserId =  map.get("adUserId").toString();
            adUserId = AESTool.decryptString(adUserId);

            if(null == adUserId){
                ParameterTool.writeResponse(response,-5, "参数adUserId错误");
                return;
            }


            Long organizationId = Long.valueOf(map.get("organizationId").toString());
            Integer organizationType = Integer.valueOf(map.get("organizationType").toString());
            String organizationName = (String) map.get("organizationName");
            Long  roleId = Long.valueOf(map.get("roleId").toString());
            Long subUserGroupId = MapUtils.getLong(map,"subUserGroupId");

            /**
             * GuidanzApp 增加了source参数
             * 此参数的目的表示WWID用户完善信息来源
             * 1：表示GuidanzApp完善WWID用户信息
             */
            int source = MapUtils.getIntValue(map, "source", -1);

            //去除姓名里边可能包含的空格回车等
            String name = (String) map.get("name");
            name = replace(name);
            String employeeNum = (String) map.get("wwid");

            // 校验短信认证码
            String phone = (String) map.get("phone");
            String verifyCode = (String) map.get("verifyCode");
            if(!validateVerifyCode(phone,verifyCode)){
                ParameterTool.writeErrorResponse(response,-6);
                return;
            }

            // 查询是否已存在用户数据
            UserT userT = loginDao.getUserByAdUserId(adUserId);
            if(null != userT){
                ParameterTool.writeErrorResponse(response,-4);
                return ;
            }

            //查询角色相关信息
            List<UserT> handlerList = null;
            Long userGroupId = rolesService.getUserGroupId(organizationId,organizationType);
            if(null == userGroupId){
                ParameterTool.writeResponse(response,3,"查无用户渠道，请联系管理员维护渠道信息");
                return;
            }


            RolesT rolesT = rolesTDao.getRolesById(roleId);
            if(null != rolesT && rolesT.getIsApproval().equals(1)){
                handlerList = rolesService.getHandlerList(organizationId,organizationType,userGroupId,roleId);
                if(CollectionUtils.isEmpty(handlerList)){
                    ParameterTool.writeResponse(response,4,"该角色暂未配置审批人，请联系相关人员维护信息");
                    return;
                }
            }

            //插入用户数据
            UserT bean = new UserT();
            bean.setAduserId(adUserId);
            bean.setCompanyId(Long.valueOf(organizationId));
            //bean.setCompanyName(organizationName);
            bean.setUserName(employeeNum);
            bean.setAzureToken("");
            bean.setContact(name);
            bean.setPhone(phone);
            bean.setType(2);
            bean.setEmployeeNum(employeeNum);

            //拼装用户组信息
            bean = rolesService.initBaseUserGroup(bean);

            //入库用户信息
            int flag = loginDao.insertUser(bean);
            if (flag <= 0) {
                // 添加用户发生异常，抛出错误
                ParameterTool.writeErrorResponse(response,-99);
                return ;
            }


            Boolean approval = false;
            /**
             * 1:表示GuidanzApp完善用户信息
             */
            if(source == 1) {
	            // 来自Guidanz app的WWID用户，完善信息时默认为终端用户
	            rolesService.initRoles(bean, rolesT.getRolesNo());
            }else {
	            // 设置默认角色
	            rolesService.initRoles(bean,SERVICE_ENGINEER_ROLE_NO);
	            // APP注册为用户添加用户组关联角色
	            approval = rolesService.addRoleOrder(organizationId,organizationName,organizationType,employeeNum,bean.getId(),rolesT,userGroupId,subUserGroupId,handlerList,1);
            }

            bean = loginDao.getUserByUserId(bean.getId());
            Map<String,Object> responseMap = new HashMap<>();
            Map<String,Object> responseDataMap = new HashMap<>();
            responseDataMap.put("userId",String.valueOf(bean.getId()));
            UserTokenT userTokenT = userTokenTMapper.selectByAdUserId(adUserId);
            mergeToken(bean.getId(),adUserId,userTokenT.getAccessToken());
            responseDataMap.put("token",userTokenT.getAccessToken());
            responseDataMap.put("isPwd",bean.getIsPwd());
            responseMap.put("data",responseDataMap);

            if(approval){
                responseMap.put("status",2);
                responseMap.put("msg","您的注册信息已提交，请耐心等待服务渠道管理员审核！在审核之前，您只能使用普通用户的功能");
                ParameterTool.writeResponse(response,JsonUtils.toJsonString(responseMap));
            }else{
                responseMap.put("status",0);
                responseMap.put("msg","success");
                ParameterTool.writeResponse(response,JsonUtils.toJsonString(responseMap));
            }
            //添加新手活动
            log.info("添加新手活动；userId:" + bean.getId());
            cipServiceApi.addNeophyteUser(bean.getId());
            //注册时接收老友会用户
            LyhFileUserRequest userRequest = new LyhFileUserRequest();
            userRequest.setUserId(bean.getId());
            userRequest.setPhone(bean.getPhone());
            externalDataSynchroService.receiveLyhUser(userRequest);
            return;
        } catch (Exception e) {
            log.error(e.getMessage(),e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            ParameterTool.writeErrorResponse(response);
            return;
        }
    }

    private Boolean validateVerifyCode(String phone,String verifyCode){
        String redisCode = redisClientUtils.get("sms" + phone);
        if (StringUtils.isEmpty(redisCode) || !verifyCode.trim().equals(redisCode)) {
           return false;
        }else{
            //redisClientUtils.delkey("sms" + phone);
            return true;
        }
    }

    @SuppressWarnings("unchecked")
	@Override
    public void register(Map map) {
        HttpServletResponse response = (HttpServletResponse) map.get("response");
        String phone = MapUtils.getString(map,"phone");
        try {
            Map<String,Object> responseMap = new HashMap<>();
            /**
             * 不同的type对应不同的注册类型
             * 终端用户：         type=1
             * 服务商用户：       type=2
             * 康明斯分公司用户： type=4
             * 康明斯员工：       type=3
             */
            Integer type = Integer.valueOf(map.get("type").toString());


            String name = map.get("name").toString();
            //去除姓名里边可能包含的空格回车等
            name = replace(name);
            String password = map.get("password").toString();
            password = AESTool.decryptString(password);
            //校验短信认证码
            String verifyCode = map.get("verifyCode").toString();
            Long subUserGroupId = MapUtils.getLong(map,"subUserGroupId");

            /**
             * 校验验证码是否正确
             */
			if(!validateVerifyCode(phone,verifyCode)){
                int timeMax = 5;
                int times = mobileSmsService.smsCodeTimes(phone,timeMax);
                if(times >= timeMax){
                    redisClientUtils.delkey("sms" + phone);
                    ParameterTool.writeErrorResponse(response,-55);
                    return ;
                }
				ParameterTool.writeErrorResponse(response,-6);
			    return;
			}

            /**
             * 校验当前的手机号是否被注册
             */
            // 查询用户信息
            List<UserT> userTList = loginDao.getUserByPhone(phone);
            if(CollectionUtils.isNotEmpty(userTList)){
            	ParameterTool.writeErrorResponse(response,-4);
                return;
            }else{
                UserT existT = loginDao.getUserByUserName(phone);
                if(null != existT){
                	ParameterTool.writeErrorResponse(response,-4);
                    return;
                }
            }

            /**
             * 校验邮箱是否已被注册
             */
            //验证邮箱是否可用
            String email = MapUtils.getString(map, "email", "");
            if(StringUtils.isNotBlank(email)) {
            	try {
            	    /**
            	     * 这种查询存在的隐患：1：数据特殊情况出现重复的邮箱时，这种查询会报错，建议sql加上top 1或用List接收
            	     */
            		UserT user = loginDao.getUserByEmail(email);
            		if(null != user) {
            			ParameterTool.writeErrorResponse(response, -30, ApiErrorCode.getInstance().getErrorMsg(-30));
                        return;
            		}
            	} catch(Exception e) {
            		ParameterTool.writeErrorResponse(response, -30, ApiErrorCode.getInstance().getErrorMsg(-30));
                    return;
            	}
            }

            //查询角色相关信息
            Long organizationId = null;
            Integer organizationType = null;
            Long userGroupId = null;
            Long  roleId = null;
            String organizationName = null;
            String employeeNum = null;
            List<UserT> handlerList = null;
            RolesT rolesT = null;
            if(!type.equals(1)){
                organizationId = Long.valueOf(map.get("organizationId").toString());
                organizationType = Integer.valueOf(map.get("organizationType").toString());
                organizationName = (String) map.get("organizationName");
                employeeNum = (String) map.get("employeeNum");
                roleId = Long.valueOf( map.get("roleId").toString());

                userGroupId = rolesService.getUserGroupId(organizationId,organizationType);
                if(null == userGroupId){
                    ParameterTool.writeResponse(response,2,"查无用户渠道，请联系管理员维护渠道信息");
                    return;
                }
                rolesT = rolesTDao.getRolesById(roleId);
                if(null != rolesT && rolesT.getIsApproval().equals(1)){
                    handlerList = rolesService.getHandlerList(organizationId,organizationType,userGroupId,roleId);
                    if(CollectionUtils.isEmpty(handlerList)){
                        ParameterTool.writeResponse(response,4,"该角色暂未配置审批人，请联系相关人员维护信息");
                        return;
                    }
                }
            }

            // 加锁处理，避免发生多次注册。
            if(!redisClientUtils.lock("registerLock-" + phone,60L)){
                ParameterTool.writeErrorResponse(response,-98);
                return;
            }

            // 分公司用户注册，校验wwid,放在锁中
            if(type == 4){
                if(StringUtils.isEmpty(employeeNum)){
                    ParameterTool.writeResponse(response,5,"您输入的WWID不存在，请确认是否正确");
                    return;
                }else{
                    String adUserId = getAdUserIdByEmployeeNum(employeeNum);
                    if(StringUtils.isEmpty(adUserId)){
                        ParameterTool.writeResponse(response,5,"您输入的WWID不存在，请确认是否正确");
                        return;
                    }else{
                        UserT adUser = loginDao.getUserByAdUserId(adUserId);
                        if(null != adUser){
                            ParameterTool.writeResponse(response,6,"您输入的WWID已绑定其他账户，请确认");
                            return;
                        }
                    }
                }
            }

            //在AD中增加用户
            String webClient_id = this.propertiesUtils.getPropertiesValue("webClient_id");
            String webClientSecret = this.propertiesUtils.getPropertiesValue("webClientSecret");
            String tenant = this.propertiesUtils.getPropertiesValue("tenant");
            //获取token
            String token = AzureADTool.getManagementToken(tenant, webClient_id, webClientSecret);
            if (null == token) {
                ParameterTool.writeErrorResponse(response);
                return;
            }

            /**
             * 添加用户到AD池
             */
            String userJson = AzureADTool.getUser(phone, tenant, token);
            if (StringUtils.isEmpty(userJson)) {
                // 2、Azure AD使用token去新建用户
                userJson = AzureADTool.addUser(phone, password, tenant, token);
                if (StringUtils.isEmpty(userJson)) {
                	ParameterTool.writeResponse(response, 10, "AD池添加用户失败");
                    return;
                }
            }else {
            	// userJson不为空时，而数据并不存在当前帐号时，说明账号已被作废或删除，那么此时需要更新AD池的密码为用户输入的新密码
            	boolean result = AzureADTool.modifyUserPassword(tenant, phone, token, password);
            	if(!result) {
            		ParameterTool.writeResponse(response, 11, "AD池已存在当前注册用户，更新新密码失败");
                    return;
            	}
            }

            /**
             * 3、保存用户数据到数据库
             *  并给用户添加默认用户组、子用户组、角色
             */
            JSONObject jsonObj = new JSONObject(userJson);
            String username = jsonObj.getString("userPrincipalName");
            String adUserId = jsonObj.getString("id");
            //插入用户数据
            UserT bean = new UserT();
            bean.setAduserId(adUserId);
            //bean.setCompanyId(Long.valueOf(organizationId));
            bean.setUserName(phone);
            bean.setContact(name);
            bean.setAzureToken("");
            bean.setPhone(phone);
            bean.setType(1);
            bean.setEmployeeNum("");
            bean.setEmail(email);
            //获取用户组
            bean = rolesService.initBaseUserGroup(bean);

            /**
             * 保存注册用户
             */
            bean.setPhotoUrl(MapUtils.getString(map, "photoUrl", ""));
            /*
                 sprint58 【IP地址解析】通过IP现有注册IP解析用户的地区  jira 5998
             */
            //获取请求的ip
            HttpServletRequest request = (HttpServletRequest) map.get("request");
            String ip = RequestIPUtils.getRequestClientRealIp(request);
            //通过IP获取 地区
            bean = GDRegion.addProviceAndCity(ip, bean);

//            int flag = loginDao.insertUser(bean);
            int flag = loginDao.insertUserAddSeat(bean);
            //添加标签
            Integer laberType = MapUtils.getInteger(map, "laberType");
            Integer downloadChannel = MapUtils.getInteger(map, "downloadChannel");
            if (null != laberType) {
                UserLabel userLabel = new UserLabel();
                userLabel.setLaberType(MapUtils.getInteger(map, "laberType"));
                userLabel.setDownloadChannel(downloadChannel);
                userLabel.setUserId(bean.getId());
                userLabel.setFlag(0);
                userLabel.setCreator(bean.getId());
                userLabel.setCreateTime(LocalTimeUtil.getRealCurrentTime());
                userLabel.setIsRead(1);
                userLabelMapper.insertSelective(userLabel);
            }
            if (flag <= 0) {
                //返回客户
                ParameterTool.writeErrorResponse(response,-99);
                return;
            }

            /**
             * 获取当前注册来源
             * source = 1 来源为Guidanz注册用户
             * 修改注册用户的企业名称
             */
            int source = MapUtils.getIntValue(map, "source", -1);
            if(source == 1) {
            	String companyName = MapUtils.getString(map, "companyName");
            	Integer userType = MapUtils.getInteger(map, "userType");

            	// 更新用户的企业跟
            	loginDao.updateUserCompanyAndUserTypeById(bean.getId(), companyName, userType);

            	/**
            	 *  Guidanz
            	 * 用户注册成功 授于访客角色
            	 */
            	addGMVisitor(bean.getId());

            	/**
            	 * 同步unionid到AD池
            	 */
            	String unionid = (type == 2) ? phone : ("8" + String.format("%08d", bean.getId()));
            	((GMApplyServiceImpl)gmApplyService).updateADCustomerAttributes(phone, type, unionid, null, null);
            }

            /**
             * 保存用户的角色权限
             */
            rolesService.initBaseRoles(bean);

            //添加新手活动
            log.info("添加新手活动；userId:" + bean.getId());
            cipServiceApi.addNeophyteUser(bean.getId());
            //注册时接收老友会用户
            LyhFileUserRequest userRequest = new LyhFileUserRequest();
            userRequest.setUserId(bean.getId());
            userRequest.setPhone(bean.getPhone());
            externalDataSynchroService.receiveLyhUser(userRequest);

            if(!type.equals(1)){
                Boolean approval= rolesService.addRoleOrder(organizationId,organizationName,organizationType,employeeNum,bean.getId(),rolesT,userGroupId,subUserGroupId,handlerList,1);
                if(approval){
                    responseMap.put("status",3);
                    if((type.equals(2) || type.equals(4)) && !rolesT.getRolesNo().equals("R0041")){
                        responseMap.put("msg","您的注册信息已提交，请联系贵站站长审核账户申请信息！在审核之前，您只能使用普通用户的功能");
                    }else{
                        responseMap.put("msg","您的注册信息已提交，请耐心等待服务渠道管理员审核！在审核之前，您只能使用普通用户的功能");

                    }
                }else{
                    responseMap.put("status",0);
                    responseMap.put("msg","success");
                }
            }else{
                responseMap.put("status",0);
                responseMap.put("msg","success");
            }

            Map<String,Object> responseDataMap = new HashMap<>();
            /**
             * 调用common系统初始化当前帐号的token
             */
            String accessToken = remoteInitToken(username, password);
            if (StringUtils.isEmpty(accessToken)) {
                ParameterTool.writeErrorResponse(response);
                return ;
            }

            /**
             * 1.刷新UserToken表里的UserId
             * 2.将token缓存到Redis
             */
            mergeToken(bean.getId(),adUserId,accessToken);

            /**
             * 用户注册成功后会直接跳转到app首页
             * 因此注册成功后需要将token信息返回到前端
             */
            bean = loginDao.getUserByUserId(bean.getId());
            responseDataMap.put("userId",String.valueOf(bean.getId()));
            responseDataMap.put("token",accessToken);
            responseDataMap.put("isPwd",bean.getIsPwd());
            responseMap.put("data",responseDataMap);
            ParameterTool.writeResponse(response, JsonUtils.toJsonString(responseMap));
        } catch (Exception e) {
            log.error(e.getMessage(),e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            ParameterTool.writeErrorResponse(response);
        } finally {
            redisClientUtils.delkey("registerLock-" + phone);
        }
    }


    private void addGMVisitor(Long userId) {
    	visitorDao.insertSelective(new GMVisitorEntity(userId, userId, LocalTimeUtil.getRealCurrentTime()));
    }


    /**
     * Guidanz注册成功后默认初始化Guest权限
//     * @param userType
//     * @param companyName
     * 废弃
     */
	/*    @Deprecated
	private void initGMLevel(Integer userType, String companyName, Long userId) {
		Map<String, Object> applyRecord = new HashMap<>();
		// 申请单号
		applyRecord.put("ApplyRecordNo", SerialNumberUtil.getGMApplyRecordNumber("GM"));
		// 用户类型
		applyRecord.put("UserType", userType);
		// 申请来源 1:表示Guidanz注册
		applyRecord.put("ApplySource", 1);
		// 注册企业名称
		applyRecord.put("CompanyName", companyName);
	    // 用户ID
		applyRecord.put("UserId", userId);
		applyRecord.put("CompanyType", 1);
		// 默认权限
		applyRecord.put("ServiceType", "Guest");

		String currentTime = LocalTimeUtil.getRealCurrentTime();
		// 权限申请时间
		applyRecord.put("ApplyTime", currentTime);
		applyRecord.put("ExpireDate", "2099-01-01");
		// 0:待审核1:已撤回2:已审核3:已拒绝4:已解除5:已过期
		applyRecord.put("Status", 2);
		// 审核通过的时间
		applyRecord.put("AuthorizeTime", currentTime);
		applyRecord.put("Creator", userId);
		applyRecord.put("CreateTime", currentTime);
			gmApplyRecordTDao.insertSelective(applyRecord);
	}*/

    @Override
    public void silentLogin(Map map) {
        HttpServletResponse response = (HttpServletResponse) map.get("response");
        String type = map.get("type").toString();
        String account = map.get("account").toString();
        //去除姓名里边可能包含的空格回车等
        account = replace(account);
        String password = map.get("password").toString();

        UserT userT = loginDao.getUserByUserName(account);
        if(null == userT){
            List<UserT> userTList = loginDao.getUserByPhone(account);
            if(CollectionUtils.isEmpty(userTList)){
                ParameterTool.writeErrorResponse(response,-3);
                return;
            }else{
                userT = userTList.get(0);
            }
        }

        String suffix;
        if("1".equals(type)){
            suffix = propertiesUtils.getPropertiesValue("tenant");
        }else{
            suffix = propertiesUtils.getPropertiesValue("innerTenant");
        }
        String username = account + "@" + suffix;
        String token = remoteInitToken(username,password);
        if(StringUtils.isEmpty(token)){
            ParameterTool.writeResponse(response,-5,"获取token失败,请检查账号密码");
            return;
        }
        Map<String,Object> responseMap = new HashMap<>();
        responseMap.put("token",token);

        if(null != userT){
            responseMap.put("userId",String.valueOf(userT.getId()));
            responseMap.put("pwd",userT.getIsPwd());
            responseMap.put("initInfo",1);
        }
        ParameterTool.writeSuccessResponse(response,responseMap);
    }

    @Override
    @Transactional
    public void bindWWID(Map map) {
        HttpServletRequest request = (HttpServletRequest) map.get("request");
        HttpServletResponse response = (HttpServletResponse) map.get("response");
        // 验证WWID是否为空
        String wwid = MapUtils.getString(map, "WWID");
        if (StringUtils.isEmpty(wwid)) {
            ParameterTool.writeErrorResponse(response, -5);
            return;
        }
        // 获取用户信息
        String userId = request.getHeader("userid");
        userId = AESTool.decryptString(userId);
        UserT userT = (UserT) redisClientUtils.getObject("userT" + userId);
        if (null != userT) {
            UserChannelT userChannelT = userChannelTMapper.getUserChannelByUserIdAndChannel(userT.getId(),"2");
            if (null != userChannelT) {
                ParameterTool.writeErrorResponse(response, -97,"老友汇用户不可绑定WWID");
                return;
            }
            // 外部用户才能进行绑定，内部用户已绑定WWID
            if (userT.getType().equals(1)) {
                // 该员工编号在AD用户池
                String adUserId = getAdUserIdByEmployeeNum(wwid);
                if (StringUtils.isNotEmpty(adUserId)) {
                    UserT existUser = loginDao.getUserByUserName(wwid);
                    UserT adUser = loginDao.getUserByAdUserId(adUserId);
                    // 判断可否绑定
                    Boolean canBind = Boolean.FALSE;
                    // 该员工编号在数据库中不存在可以绑定
                    if(null == existUser && null == adUser){
                        canBind = Boolean.TRUE;
                    }else{
                        // 该员工编号在数据库存在，但是是当前用户可以绑定
                        if(null != existUser && existUser.getId() == userT.getId()){
                            canBind = Boolean.TRUE;
                        }
                    }
                    if (canBind) {
                        userT.setAduserId(adUserId);
                        userT.setUserName(wwid);
                        userT.setType(2);
                        userT.setEmployeeNum(wwid);
                        userTDao.updateByPrimaryKeySelective(userT);
                        redisClientUtils.delkey("userT" + userId);
                    } else {
                        ParameterTool.writeResponse(response, 3, "该WWID已被他人绑定，请确认输入是否正确！");
                        return;
                    }
                } else {
                    ParameterTool.writeResponse(response, 2, "未知WWID信息，请确认输入是否正确！");
                    return;
                }
            } else {
                ParameterTool.writeResponse(response, 1, "您已绑定WWID信息，请勿重复绑定！");
                return;
            }
        }
        ParameterTool.writeSuccessResponse(response);
    }

    @Override
    public void bindPromotionId(Map map) {
        HttpServletResponse response = (HttpServletResponse) map.get("response");
        UserT userT = UserThreadLocal.get();
        String promotionId = MapUtils.getString(map,"promotionId");
        if(StringUtils.isNotEmpty(promotionId)){
            UserT existUser = userTDao.getUserByPromotionId(promotionId);
            if(null != existUser && existUser.getId() != userT.getId()){
                ParameterTool.writeResponse(response,1,"该授权资质ID已被其他用户绑定，请确认输入！");
                return;
            }
            userT = userTDao.selectById(userT.getId());
            userT.setPromotionId(promotionId);
            userTDao.updateByPrimaryKeySelective(userT);
            redisClientUtils.delkey("userT" + userT.getId());
            ParameterTool.writeSuccessResponse(response);
        }else{
            ParameterTool.writeErrorResponse(response,-5);
        }
    }

    private String getAdUserIdByEmployeeNum(String employeeNum) {
        String adUserId = null;
        if (StringUtils.isNotEmpty(employeeNum) && WWID_PATTERN.matcher(employeeNum).matches()) {
            String webClientId = this.propertiesUtils.getPropertiesValue("webClient_id");
            String webClientSecret = this.propertiesUtils.getPropertiesValue("webClientSecret");
            String tenant = this.propertiesUtils.getPropertiesValue("tenant");
            String innerTenant = this.propertiesUtils.getPropertiesValue("innerTenant");
            //获取token
            String token = AzureADTool.getManagementToken(tenant, webClientId, webClientSecret);
            //查询用户信息
            String userJson = AzureADTool.getUser(employeeNum, innerTenant, token);
            //用户存在，说明该用户为内部用户
            if (StringUtils.isNotEmpty(userJson)) {
                Map<String, Object> userMap = JsonUtils.toJavaObject(userJson, Map.class);
                adUserId = (String) userMap.get("id");
            }
        }
        return adUserId;
    }

    private void mergeToken(Long userId,String adUserID,String token){
        redisClientUtils.delkey(RedisKeys.tokenKey(token));
        UserTokenT userTokenT = userTokenTMapper.selectByAdUserId(adUserID);
        if(null != userTokenT){
            userTokenT.setUserId(userId);
            userTokenTMapper.updateByPrimaryKeySelective(userTokenT);
            redisClientUtils.set(RedisKeys.tokenKey(userTokenT.getAccessToken()),JsonUtils.toJsonString(userTokenT),3540);
        }
    }

    private String replace(String str){
        if (StringUtils.isNotEmpty(str)) {
            Pattern p = Pattern.compile("\t|\r|\n");
            Matcher m = p.matcher(str);
            str = m.replaceAll("");
            return str.trim();
        }
        return null;
    }

    /**
     * 删除账号
     */
    @Override
    public boolean delete(Map<String, Object> map) {
        try{
            HttpServletRequest request = (HttpServletRequest)map.get("request");

            /**
             * 使用Azure Ad删除用户
             */
            String AUTHORITY = this.propertiesUtils.getPropertiesValue("authority");
            String RESOURCE = this.propertiesUtils.getPropertiesValue("resource");
            String webClient_id = this.propertiesUtils.getPropertiesValue("webClient_id");
            String webClientSecret = this.propertiesUtils.getPropertiesValue("webClientSecret");
            String tenant = this.propertiesUtils.getPropertiesValue("tenant");
            AUTHORITY = AUTHORITY.replace("common", tenant);
            /**
             * 1、Azure Ad获取token
             */
            IAuthenticationResult result = AzureADTool.getAccessTokenByClient(webClient_id, webClientSecret,AUTHORITY,RESOURCE);
            if(result == null){
                map.put("result", "false");
                return false;
            }

            String funids = ""+map.get("funids");
            List<Long> idsList = new ArrayList<Long>();
            if(!funids.equals("")){
                String[] ids = funids.split(",");
                for(String id : ids){
                    idsList.add(Long.valueOf(id));
                }
            }

            List<UserT> users = userTDao.getUsersByIds(idsList);
            for(UserT u : users) {
                // 用户为内部用户，或是用户名符合WWID，只做本地删除
                if(u.getType() == 2 || WWID_PATTERN.matcher(u.getUserName()).matches()){
                    continue;
                }else{
//                     调用AD删除用户接口
//                    boolean delFlag = AzureADTool.deleteAzureUser(u.getAduserId(), RESOURCE, result.accessToken(), tenant);
//                    if(!delFlag) {
//                        idsList.remove(u.getId());
//                    }
                }
                /**
                 * 查询  微信和 用户的  关系表    WeChatUserRelation_T；
                 * 如果有的话，就更新
                 */
                List<WeChatUserRelationT> weChatUserRelationTS = weChatUserRelationTDao.selectRelationTByOpenIdAndFlagList(u.getId(), 0);
                if (org.apache.commons.collections.CollectionUtils.isNotEmpty(weChatUserRelationTS)) {
                    for (WeChatUserRelationT weChatUserRelationT : weChatUserRelationTS) {
                        weChatUserRelationT.setFlag(-1);
                        int i = weChatUserRelationTDao.updateRelationTStatusByOpenId(weChatUserRelationT);
                    }

                }
            }

            HttpServletResponse response = (HttpServletResponse)map.get("response");

            if(org.apache.commons.collections.CollectionUtils.isEmpty(idsList)) {
                return false;
            }

            boolean flag = userTDao.deleteDate(idsList);

            //技师删除同步芯管家服务站
            List<UserT> userList = userTDao.getUsersByIds(idsList);
            for(UserT userT : userList){
                int xinIsXgj = userTDao.getXgjRoleList(userT.getId());
                if(xinIsXgj > 0){
                    cipServiceApi.updateXgjFleetUserId(userT.getId(),userT.getServiceStationID());
                }
                //同步删除cip车辆和车队
                externalDataSynchroService.deleteEsnAndFleet(userT.getId());
            }

            if (flag) {
                //日志
                for(Long id : idsList){

                    redisClientUtils.delkey(RedisKeys.userKey(String.valueOf(id)));
                    UserTokenT userTokenT = userTokenTMapper.selectByUserId(id);
                    if(null != userTokenT){
                        redisClientUtils.delkey(RedisKeys.tokenKey(userTokenT.getAccessToken()));
                    }
                    aKeyLoginUserTokenDao.deleteTokenByUserId(id,1);
                    userTokenTMapper.deleteTokenByUserId(id);
                    SystemLogsT systemLogsT = new SystemLogsT();
                    systemLogsT.setUserId(id);
                    systemLogsT.setTname("User_T");
                    systemLogsT.setTid(id);
                    systemLogsT.setActionName("del");//操作方法
                    systemLogsT.setRemark("删除用户");
                    loginDao.insertSystemLogs(systemLogsT);
                }

                return true;
            } else {
                return false;
            }
        }catch(Exception ex){
            log.error(ex.getMessage(), ex);
        }
        return false;
    }

    /**
     * app用户退出登录接口
     * @param request
     * @return
     */
    @Override
    public boolean appLoginOut(HttpServletRequest request, HttpServletResponse response) {
        String userid = request.getHeader("userid");
        String token = request.getHeader("Authorization");
        userid = AESTool.decryptString(userid);
        Long userId = Long.valueOf(userid);
        redisClientUtils.delkey("userT" + userid);
        redisClientUtils.delkey(RedisKeys.tokenKey(token));
        aKeyLoginUserTokenDao.deleteTokenByUserId(userId,1);
        userTokenTMapper.deleteTokenByUserId(userId);
        return true;
    }

}
